#!/usr/bin/env python
# -*- coding: utf-8 -*-

__library__ = "pyflowctrl"
__dependencies__ = []
__training_set__ = ""
__links__ = []
__author__ = ["Andrey Usov <http://devel.ownport.net>",]
__version__ = "20120116"
__all__ = ['PyMetaInfo',]
__doc__ = '''Generate meta description for python module. Based on lib/pydoc.py'''

import pkgutil
import inspect

from pydoc import locate, isdata, visiblename

from pyflowctrl.core4 import Stream, Process, EmptyStream
from pyflowctrl.core4 import WAITING, PROCESSING

STREAM = {}

class PyMetaInfo(Process):
    ''' Extact metadata information about module/class '''
    
    input = Stream()
    output = Stream()

    
    def __init__(self):
        super(PyMetaInfo, self).__init__()
        #self.input = Stream()
        #self.output = Stream()

    def get_elements(self, obj, element_type):
        ''' get list of object's elements by type'''
        try:
            all = obj.__all__
        except AttributeError:
            all = None
        elements = []
        for key, value in inspect.getmembers(obj, element_type):
            if visiblename(key, all, value):
                elements.append((key, value))
        return elements

    def get_classes(self, obj):
        ''' get list of classes '''
        classes = []
        for c in self.get_elements(obj, inspect.isclass):
            c = list(c)
            c.extend(c[1].__bases__)
            classes.append(tuple(c))
        return classes        

    def get_modpkgs(self, obj):
        ''' get list of module's packages '''
        modpkgs = []
        modpkgs_names = set()
        if hasattr(obj, '__path__'):
            for importer, modname, ispkg in pkgutil.iter_modules(obj.__path__):
                modpkgs_names.add(modname)
                if ispkg:
                    modpkgs.append(modname + ' (package)')
                else:
                    modpkgs.append(modname)
            modpkgs.sort()
        return modpkgs

    def get_metadata(self, obj):
        ''' get dictionary of object's metadata '''
        metadata = {}
        if obj == None:
            return metadata
        metadata['name'] = obj.__name__        
        metadata['type'] = type(obj)
        metadata['description'] = inspect.getdoc(obj) or inspect.getcomments(obj)
        metadata['classes'] = self.get_classes(obj)
        metadata['funcs'] = self.get_elements(obj, inspect.isroutine)
        metadata['data'] = self.get_elements(obj, isdata)
        metadata['module_packages'] = self.get_modpkgs(obj)
        metadata['submodules'] = self.get_elements(obj, inspect.ismodule)

        if hasattr(obj, '__bases__'):
            metadata['based_on'] = obj.__bases__
        
        cleared_meta = {}
        for k in metadata:
            if metadata[k]:
                cleared_meta[k] = metadata[k]
        
        return cleared_meta

    def main(self):
        while True:
            try:
                packet = self.input.get()
            except EmptyStream:
                yield WAITING
                continue
                
            
            obj = locate(packet.module)
            packet.meta = self.get_metadata(obj)
                
            self.output.put(packet)
            yield PROCESSING

    
    
    
